/**
  ******************************************************************************
  * @file    WinCommThread.h
  * @brief   cpp file for thread class
  * @author  wf.chen[wf.chen@signway.cn]
  * @version V1.0.0
  * @date    2020/03/09
  ******************************************************************************
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * COPYRIGHT 2020 Signway NanJing Ltd.
  *
  ******************************************************************************
  */

#include "threading.h"
#include "log_err.h"

struct ThreadData {
    Thread *instance;
    uint32_t data;
};

static void *ThreadShim(void *opaque)
{
    // defer processing to the virtual function implemented in the derived class
    ThreadData *threadData = reinterpret_cast<ThreadData *>(opaque);
    Thread *instance = threadData->instance;

    if (threadData->data == 0) {
        instance->threadMain();
    } else {
        instance->threadMain(threadData->data);
    }

    delete threadData;

    return nullptr;
}


bool Thread::start(uint32_t data, bool detach) {
    ThreadData *threadData = new ThreadData();
    threadData->instance = this;
    threadData->data = data;
    SIGNWAY_LOGI("");
    threads.push(std::move(std::thread(ThreadShim, threadData)));
    SIGNWAY_LOGI("");
    if (detach) {
        threads.back().detach();
    }
    return true;
}

void Thread::stop()
{
    if (!threads.empty()) {
        SIGNWAY_LOGI("");
        if (threads.front().joinable()) {
            threads.front().join();
        }
        threads.pop();
    }
}

Thread::~Thread()
{
    while (!threads.empty()) {
        if (threads.front().joinable()) {
            threads.front().join();
        }
        threads.pop();
    }
}

Thread::Thread()
{
    
}
